#pragma once
#include <d3dx9.h>
#include <dinput.h>

#include <vector>
#include <list>
#include <set>
#include <memory>

namespace poly
{
	// integral types
	typedef unsigned char	uint8;
	typedef unsigned short	uint16;
	typedef unsigned int	uint32;

	typedef signed char		int8;
	typedef signed short	int16;
	typedef signed int		int32;

	// typedefs
	typedef D3DXVECTOR2 float2;
	typedef D3DXVECTOR3 float3;
	typedef D3DXVECTOR4 float4;

	typedef D3DCOLOR	colorRGB;

	typedef D3DXMATRIX float44;

	typedef WCHAR text; 

	// constants
	extern const float PI;
	extern const float TWO_PI;

	// float33 class
	struct float33
	{
		union
		{
			struct
			{
				float xx, xy, xz;
				float yx, yy, yz;
				float zx, zy, zz;
			};

			struct
			{
				float3 rowx;
				float3 rowy;
				float3 rowz;
			};

			struct
			{
				float3 row[3];
			};

			float f[3][3];
		};

		// cast operators
		operator float* ();
		operator float const * () const;

		// assignment operators
		float33& operator*=( float33 const & m );
		float33& operator+=( float33 const & m );
		float33& operator-=( float33 const & m );
		float33& operator*=( float s );
		float33& operator/=( float s );

		// unary operators
		float33 operator+() const;
		float33 operator-() const;

		// binary operators
		float33 operator*( float33 const & m ) const;
		float33 operator+( float33 const & m ) const;
		float33 operator-( float33 const & m ) const;
		float33 operator*( float s ) const;
		float33 operator/( float s ) const;

		// friend operators
		friend float33 operator*( float s, float33 const & m );
		friend float3 operator*( float3 const &vec, float33 const & mat );
	};

	//Ray
	struct ray3
	{
		float3 origin;
		float3 direction;
	};

	struct Line
	{
		float3 point;
		float3 normal;
	};

	struct Segment
	{
		float3 point0;
		float3 point1;
	};

	void transformRay(ray3* ray, float44* T);

	// vector and matrix functions
	float3 zero3();
	float4 zero4();
	float33 zero33();
	float44 zero44();

	float33 identity33();
	float33 smallRotation( float3 rot );
	float33 rotationAxis( float3 axis, float angle );
	
	float44 identity44();

	float length( float3 const &vec );
	float lengthSq( float3 const &vec );
	float3 normalize( float3 const &vec );

	float dot( float3 const &vec1, float3 const &vec2 );
	float3 cross( float3 const &vec1, float3 const &vec2 );

	bool rightHanded( float3  const &a, float3 const &b, float3 const &c );

	float determinant( float33 const & mat );
	float33 crossing( float3 const &vec );
	float33 projection( float3 const &vec );

	float33 transpose( float33 const & mat );
	float33 inverse( float33 const & mat );

	float3 transformNormal( float3 const & vec, float44 const & mat );
	float3 transformCoord( float3 const & vec, float44 const & mat );

	float44 augment( float33 const & mat );

	float44 translation( float3 const & vec );

	float44 lookAtLH( float3 eye, float3 at, float3 up );
	float44 lookAtRH( float3 eye, float3 at, float3 up );

	float44 orthoLH( float w, float h, float zn, float zf );
	float44 orthoRH( float w, float h, float zn, float zf );

	float44 orthoOffCenterLH( float l, float r, float b, float t, float zn, float zf );
	float44 orthoOffCenterRH( float l, float r, float b, float t, float zn, float zf );

	float44 perspectiveLH( float w, float h, float zn, float zf );
	float44 perspectiveRH( float w, float h, float zn, float zf );

	float44 perspectiveFovLH( float fovy, float Aspect, float zn, float zf );
	float44 perspectiveFovRH( float fovy, float Aspect, float zn, float zf );

	float44 perspectiveOffCenterLH( float l, float r, float b, float t, float zn, float zf );
	float44 perspectiveOffCenterRH( float l, float r, float b, float t, float zn, float zf );

	/*****************
	Color definitions
	******************/
	#define COLOR_BLACK		float3	(0,0,0)
	#define COLOR_BLUE		float3	(0,0,255)
	#define COLOR_CYAN		float3	(0,255,255)
	#define COLOR_GREEN		float3	(0,255,0)
	#define COLOR_MAGENTA	float3	(255,0,255)
	#define COLOR_RED		float3	(255,0,0)
	#define COLOR_WHITE		float3	(255,255,255)
	#define COLOR_YELLOW	float3	(255,255,0)

	// D3D Stuff
	typedef IDirect3DDevice9*				D3DDevice;
	typedef IDirect3DVertexBuffer9*			VertexBuffer;
	typedef IDirect3DVertexDeclaration9*	VertexDeclaration;
	typedef IDirect3DIndexBuffer9*			IndexBuffer;
	typedef ID3DXEffect*					Effect;
	typedef	D3DXHANDLE						EffectHandle;
	typedef	ID3DXFont*						Font;
	typedef	D3DXFONT_DESC					FontDescription;

	// DInput Stuff
	typedef IDirectInput8*					DInput;
	typedef IDirectInputDevice8*			DIDevice;

} // end of poly
